package com.sharelords.biz.util;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.*;

/**
 * @author 千古龙少
 * @Description: 属性映射工具类，将T1映射到T2，只能映射字段名和类型相同的的属性
 * @date 2019年2月6日 下午3:41:24
 */
public class InvokeUtil {

    /**
     * 泛型初始化
     *
     * @param clazz 目标对象class类型
     * @return T
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:13
     */
    private static <T> T getInvokeUtil(Class<T> clazz) {
        T t = null;
        try {
            t = clazz.getConstructor().newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * source对象数据存储到target
     *
     * @param source 数据源对象
     * @param clazz  目标对象class类型
     * @return T
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:14
     */
    public static <T> T copy(Object source, Class<T> clazz) {
        if (source == null) {
            return null;
        }
        if (source.getClass().equals(clazz)) {
            return (T) source;
        }

        T target = getInvokeUtil(clazz);
        BeanUtils.copyProperties(source, target);

        return target;
    }

    /**
     * source集合对象数据存储到target集合
     *
     * @param source 数据源对象
     * @param clazz  目标对象class类型
     * @return java.util.List<T>
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:16
     */
    public static <T> List<T> copyList(List<?> source, Class<T> clazz) {
        List<T> targetList = new ArrayList<>();
        if (source != null && !source.isEmpty()) {
            for (Object s : source) {
                if (s == null) {
                    continue;
                }
                T t = copy(s, clazz);
                targetList.add(t);
            }
        }
        return targetList;
    }

    /**
     * 数组转list
     *
     * @param array
     * @return java.util.List<T>
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:17
     */
    public static <T> List<T> toList(T[] array) {
        if (array == null || array.length == 0) {
            return Collections.emptyList();
        }

        return new ArrayList<>(Arrays.asList(array));
    }

    /**
     * list数据转换，不去重
     *
     * @param origList
     * @param child
     * @return java.util.List<T>
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:17
     */
    public static <T, D> List<T> transList(List<D> origList, Child<T, D> child) {
        if (origList == null || origList.isEmpty()) {
            return Collections.emptyList();
        }
        List<T> resultList = new ArrayList<>();
        for (D d : origList) {
            if (d == null) {
                continue;
            }
            T group = child.group(d);
            if (group == null) {
                continue;
            }
            resultList.add(group);
        }
        return resultList;
    }

    /**
     * list数据转换Map
     *
     * @param origList
     * @param childForMap
     * @return java.util.Map<KEY, VALUE>
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:18
     */
    static <KEY, VALUE, D> Map<KEY, VALUE> transList2Map(List<D> origList, ChildForMap<KEY, VALUE, D> childForMap) {
        if (origList == null || origList.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<KEY, VALUE> resultMap = new HashMap<>();
        for (D d : origList) {
            if (d == null) {
                continue;
            }
            SimpleEntry<KEY, VALUE> simpleEntry = childForMap.group(d);
            if (simpleEntry == null || simpleEntry.getKey() == null) {
                continue;
            }
            resultMap.put(simpleEntry.getKey(), simpleEntry.getValue());
        }
        return resultMap;
    }


    /**
     * 从list中搜索某元素，并转换输出
     *
     * @param origList
     * @param child
     * @return T
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:18
     */
    static <T, D> T searchFromList(List<D> origList, Child<T, D> child) {
        if (origList == null || origList.isEmpty()) {
            return null;
        }
        for (D d : origList) {
            if (d == null) {
                continue;
            }
            T group = child.group(d);
            if (group == null) {
                continue;
            }
            return group;
        }
        return null;
    }

    /**
     * list转String，逗号分隔
     *
     * @param list
     * @return java.lang.String
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:18
     */
    public static <D> String joinList2Str(List<D> list) {
        if (list == null || list.isEmpty()) {
            return "";
        }

        return StringUtils.join(list.toArray(), ",");
    }

    /**
     * @Description: 元素处理实现逻辑
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:18
     */
    public abstract static class Child<T, D> {

        /**
         * 需复写的方法
         *
         * @param d
         * @return T
         * @Author: 千古龙少
         * @Time: 2019/12/7 19:19
         */
        public abstract T group(D d);
    }

    /**
     * @Description: 元素处理实现逻辑
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:19
     */
    public abstract static class ChildForMap<KEY, VALUE, D> {

        /**
         * 需复写的方法
         *
         * @param d
         * @return com.sharelords.biz.util.InvokeUtil.SimpleEntry<KEY, VALUE>
         * @Author: 千古龙少
         * @Time: 2019/12/7 19:19
         */
        public abstract SimpleEntry<KEY, VALUE> group(D d);
    }

    /**
     * @Description: 简易entry对象
     * @Author: 千古龙少
     * @Time: 2019/12/7 19:19
     */
    public static class SimpleEntry<KEY, VALUE> {

        private KEY key;
        private VALUE value;

        SimpleEntry(KEY key, VALUE value) {
            super();
            this.key = key;
            this.value = value;
        }

        KEY getKey() {
            return key;
        }

        public VALUE getValue() {
            return value;
        }
    }

}
